<?php
/*
 * Quark PHP Framework
 * Copyright 2011, Sahib Alejandro Jaramillo Leo.
 * http://quarkphp.com/
 * Licensed under the GNU General Public License (http://www.gnu.org/licenses/gpl.html).
 */
/**
 * Clase estatica Quark
 * @author sahib
 */
class Quark {

	/**
	 * Controlador instanciado
	 * @see Quark::getController()
	 * @access private
	 * @var Controller
	 */
	private static $Controller;

	/**
	 * Version del framework
	 * @access public
	 * @var string
	 */
	const VERSION = '1.2.2-A';

	/**
	 * Realiza todas las tareas necesarias para cargar la configuracion y ejecutar el "action" solicitado en la URL
	 * @access public
	 */
	public static function bigBang( ) {

		/*
		 * Configuracion del entorno
		 */
		self::configEnv( );
		
		// Obtener la URI
		if( isset( $_SERVER['PATH_INFO'] ) )
			$uri = $_SERVER['PATH_INFO'];
		elseif( isset($_SERVER['ORIG_PATH_INFO']) )
			$uri = $_SERVER['ORIG_PATH_INFO'];
		elseif( isset($_GET) AND strpos(key($_GET),'/') !== FALSE )
			$uri = key($_GET);
		else
			$uri = (Lang::onMultiLangMode( ) && !Lang::onSubdomain( ) ? '/' . Lang::getLangDefault( ) : NULL) . '/' .
				 Config::get( 'default_controller' ) . '/' . Config::get( 'default_action' );
			
		// Extraer y definir lenguaje para esta ejecucion.
		if( Lang::onMultiLangMode( ) ) {
			
			// Extraer el lenguaje del sub-dominio
			if( Lang::onSubdomain( ) ) {
				$domain_parts = explode( '.', $_SERVER['HTTP_HOST'] );
				if( array_search( $domain_parts[0], Lang::getLangs( ) ) != FALSE ) {
					Lang::setLang( $domain_parts[0] );
				}
				unset( $domain_parts );
			}
			// Extraer el lenguaje de la uri
			else {
				$uri_lang = array_pad( explode( '/', $uri, 3 ), 3, '' );
				if( array_search( $uri_lang[1], Lang::getLangs( ) ) !== FALSE ) {
					Lang::setLang( $uri_lang[1] );
					$uri = '/' . $uri_lang[2];
				}
			}
		}
		
		// Fixear la URI utilizando las rutas deinidas en config.php
		$uri = Url::enroute( $uri );
		
		// Formar la URI con sus valores por default en caso de no estar formada.
		$uri_parts = preg_split( '@/@', kill_slashes( $uri ) );
		
		if( empty( $uri_parts[0] ) )
			$uri_parts[0] = Config::get( 'default_controller' );
		if( empty( $uri_parts[1] ) )
			$uri_parts[1] = Config::get( 'default_action' );
		
		Url::setUriParts( $uri_parts );
		
		// Establecer nombres de controller y action
		Controller::setRunningControllerName( $uri_parts[0] );
		Controller::setRunningActionName( $uri_parts[1] );
		
		Controller::setRequestedControllerName( $uri_parts[0] );
		Controller::setRequestedActionName( $uri_parts[1] );
		
		/*
		 * Todo listo para instanciar el controlador.
		 * Aplicamos el primer HAX antes de crear el controlador
		 */
		if( is_file('includes/'.Config::get('before_controller')) )
			require 'includes/'.Config::get('before_controller');
		
		
		// Validar si existe el script del controller
		$controller_filepath = 'controllers/' . Controller::getRunningControllerName( ) . '.php';
		
		if( !is_file( $controller_filepath ) ) {
			Controller::setRunningControllerName( 'NoControllerReceptor' );
		}
		
		/*
		 * Instanciar controlador
		 */
		$running_controller_name = Controller::getRunningControllerName( );
		self::$Controller = new $running_controller_name( );
		
		// Validar si existe el action
		if( !method_exists( self::$Controller, Controller::getRunningActionName( ) ) ) {
			Controller::setRunningActionName( 'noActionReceptor' );
		}
		
		// Validar nivel de acceso al action
		if( self::$Controller->SignedUser->getAccessLevel( ) < self::$Controller->getActionAccessLevel( ) ) {
			
			// Access denied global
			if( Config::get( 'access_denied_uri' ) != NULL ) {
				$access_denied_uri = explode( '/', Config::get( 'access_denied_uri' ) );
				self::$Controller = new $access_denied_uri[0]( );
				self::$Controller->$access_denied_uri[1]( );
			}
			// Access denied generico
			else {
				self::$Controller->accessDenied( );
			}
		}
		// Acceso valido
		else {
			
			$running_action_name = Controller::getRunningActionName( );
			
			// Pasar argumentos de la url al action
			if( count( $uri_parts ) > 2 )
				eval( 'self::$Controller->$running_action_name(' . args2str( array_slice( $uri_parts, 2 ) ) . ');' );
			else
				self::$Controller->$running_action_name( );
		}
	}

	/**
	 * Devuelve el controlador en ejecucion
	 * @return Controller controlador
	 */
	public function getRunningController( ) {

		return self::$Controller;
	}

	/**
	 * Busca mensajes de error en el buffer, en caso de encontrarlos devuelve un nuevo buffer con los mensajes de error formateados.
	 * @access public
	 * @param string $buffer buffer
	 * @return string buffer procesado
	 */
	public static function obHandler( $buffer ) {

		chdir( dirname( $_SERVER['SCRIPT_FILENAME'] ) );
		if( preg_match_all( "|<phperror>(.*)</phperror>|Uis", $buffer, $matches ) > 0 ) {
			
			$errors = implode( "\n", array_map( create_function( '$a', 'return strip_tags(trim($a));' ), $matches[1] ) );
			self::log( $errors );
			
			// Renderear custom view si fué definada
			$custom_view = View::getCustomErrorView( );
			if( $custom_view != NULL and is_file( 'views/' . $custom_view . '.php' ) ) {
				require 'views/' . $custom_view . '.php';
				$new_contents = ob_get_contents( );
				$buffer = substr( $new_contents, strlen( $buffer ) );
			}
			// Mostrar errores de manera generica
			else {
				if( Ajax::onAjaxMode( ) == FALSE ) {
					$buffer = '<b>Error</b><pre>' . $errors . '</pre>';
				}
				else {
					$AjaxResp = new Ajax( );
					$AjaxResp->setError( $errors );
					$buffer = $AjaxResp->getJson( );
				}
			}
		}
		return $buffer;
	}

	/**
	 * Carga archivos de configuracion y establece algunos flags, este metodo es vital para bigBang
	 * @access private
	 */
	private static function configEnv( ) {

		Config::load( 'quark/base_config.php' );
		if( is_file( 'config/config.php' ) ) {
			Config::load( 'config/config.php' );
		}
		
		// Error reporting flag
		error_reporting( Config::get( 'error_reporting' ) );
		
		/*
		 * Agregar auto instances
		 */
		$auto_instances = array( 
			'SignedUser', 
			'Css', 
			'Js' 
		);
		
		// Agregar "Lang" a la lista de auto instances solo si es necesario.
		if( Lang::onMultiLangMode( ) ) {
			$auto_instances[] = 'Lang';
		}
		if( Ajax::onAjaxMode( ) ) {
			$auto_instances[] = 'Ajax';
		}
		
		Controller::setAutoInstances( array_merge( $auto_instances, Config::get( 'auto_instances' ) ) );
		
		// Establecer lenguaje para esta ejecucion
		if( Lang::onMultiLangMode( ) ) {
			Lang::setLang( Lang::getLangDefault( ) );
		}
		
		/*
		 * Scritps
		 */
		if( is_array( Config::get( 'includes' ) ) ) {
			foreach( Config::get( 'includes' ) as $file ) {
				if( is_file( 'includes/' . $file . '.php' ) ) {
					require 'includes/' . $file . '.php';
				}
			}
		}
	}

	/**
	 * Loggea un mensaje en debug.log
	 * @access public
	 * @param string $msg mensaje
	 * @return bool TRUE si tiene exito, de lo contrario FALSE
	 */
	public static function log( $msg ) {

		// lineas separadoras
		return @file_put_contents( 'quark.log', 
			sprintf( "[%s]\n%s\n%s\n", date( 'Y-m-d H:i:s' ), $msg, str_repeat( '-', 100 ) ), FILE_APPEND );
	}

	/**
	 * Hace un <pre>var_dump(...)</pre> de $var y despues un exit()
	 * @access public
	 * @param mixed $var,.. lista de parametros para dumpear
	 */
	public static function dump( ) {

		echo '<pre>';
		foreach( func_get_args( ) as $var ) {
			var_dump( $var );
		}
		echo '</pre>';
		exit( );
	}

	/**
	 * @deprecated
	 * @see Url::getBaseUrl()
	 */
	public static function getWebUrl( ) {

		return Url::getBaseUrl( );
	}

	/**
	 * @deprecated
	 * @see Config::get()
	 */
	public static function getConfigVal( $k ) {

		return Config::get( $k );
	}
}